package com.meituan.verintreport.task;

import com.meituan.verintreport.db.dao.ReportAdjusting1stDepartmentDao;
import com.meituan.verintreport.db.dto.ReportAdjusting1stDepartmentDto;
import com.meituan.verintreport.db.verint.VerintEvalDataDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

/**
 * 校准明细表
 */
@Slf4j
@Component
//@ConfigurationProperties(prefix = "report.adjusting-1stdepartment")
public class ReportAdjusting1stDepartmentTasks extends BaseTableTask {
    @Resource
    private ReportAdjusting1stDepartmentDao reportAdjusting1stDepartmentDao;

    @Resource
    private VerintEvalDataDao verintEvalDataDao;

    //@Value("${report.adjusting-1stdepartment.execute.maxMinutesPerTime}")
    private int maxMinutesPerTime = 15;

   // @Value("${report.adjusting-1stdepartment.count.per.batch}")
    private int countPerBatch = 1000;

    //@Value("${report.adjusting-1stdepartment.forms}")
    private String forms = "";

   // @Value("${report.adjusting-1stdepartment.timezone}")
    private String reportTimeZone;

    //@Value("${report.adjusting-1stdepartment.compensate.enable}")
    private boolean isCompensate;
   // @Value("${report.adjusting-1stdepartment.compensate.start}")
    private String compensateStart;
   // @Value("${report.adjusting-1stdepartment.compensate.end}")
    private String compensateEnd;

    private static String prevEndTimeStr = null;

    private void doCompensate() {

        log.info("doCompensate startTime = {} endTime = {}", compensateStart, compensateEnd);

        String[] formKeys = forms.split(",");

        for (String formKeyString : formKeys) {

            int formKey = 0;
            try {
                formKey = Integer.valueOf(formKeyString);
            } catch (Exception e) {
                log.warn("Can't parse key to Integer: {}", formKey);
                continue;
            }
            int pageIndex = 0;
            int pageSize = countPerBatch;

            boolean isFirst = false;

            String lastSyncTime = reportAdjusting1stDepartmentDao.getLastSyncTime();
            log.info("last sync time: {}", lastSyncTime);

            boolean shouldContinue = false;
            do {
                shouldContinue = false;

                boolean success = true;
                do {
                    success = true;
                    try {
                        List<ReportAdjusting1stDepartmentDto> records = verintEvalDataDao.getReportAdjustingFor1stDepartmentPaged(formKey, compensateStart, compensateEnd, pageIndex, pageSize);
                        log.info("got {} records for ReportAdjusting1stDepartment", records.size());
                        if (records.size() == countPerBatch) {
                            shouldContinue = true;
                        }

                        for (ReportAdjusting1stDepartmentDto record : records) {
                            try {
                                reportAdjusting1stDepartmentDao.insert(record);
                            } catch (Exception ex) {
                                log.error("Add report detail for ReportAdjusting1stDepartment to db exception.", ex);
                            }
                        }

                        pageIndex += pageSize;
                    } catch (Exception ex) {
                        success = false;
                    }
                } while (!success);
            }
            while (shouldContinue);
        }

        log.info("doCompensate end");
    }

   // @Scheduled(cron = "${report.adjusting-1stdepartment.execute.cron}")
    public void execute() {

        if (isCompensate) {
            isCompensate = false;
            doCompensate();
        }

        if (!isEnable()) return;

        do_execute();
    }
    public void do_execute() {
        Calendar beforeTime = Calendar.getInstance();
        TimeZone timezone = TimeZone.getTimeZone(reportTimeZone);
        beforeTime.setTimeZone(timezone);
        beforeTime.add(Calendar.HOUR_OF_DAY, -2);// 1小事之前的时间
        beforeTime.set(Calendar.MINUTE, 0);
        beforeTime.set(Calendar.SECOND, 0);
        beforeTime.set(Calendar.MILLISECOND, 0);
        Date beginTime = beforeTime.getTime();

        Calendar beforeTime1 = Calendar.getInstance();
        beforeTime1.setTimeZone(timezone);
        beforeTime1.add(Calendar.HOUR_OF_DAY, -1);
        beforeTime1.set(Calendar.MINUTE, 0);
        beforeTime1.set(Calendar.SECOND, 0);
        beforeTime1.set(Calendar.MILLISECOND, 0);
        Date endTime = beforeTime1.getTime();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(timezone);

        String startTimeStr = sdf.format(beginTime) + ".000";
        String endTimeStr = sdf.format(endTime) + ".000";

        log.info("timezone = {} startTime = {} endTime = {}", timezone.getDisplayName(), startTimeStr, endTimeStr);

        if (prevEndTimeStr == null) {
        } else {
            if (!prevEndTimeStr.equals(startTimeStr) && endTimeStr.compareTo(prevEndTimeStr) > 0) {
                startTimeStr = prevEndTimeStr;

                log.info("May be missed fire : {}", startTimeStr);
                log.info("Run with compensate time range: startTime = {} endTime = {}", startTimeStr, endTimeStr);
            } else {
                if (prevEndTimeStr.equals(endTimeStr)) {
                    log.warn("Time range could be fired (ignore this): startTime = {} endTime = {}", startTimeStr, endTimeStr);
                    return;
                }
            }
        }

        prevEndTimeStr = endTimeStr;

        String[] formKeys = forms.split(",");

        for (String formKeyString : formKeys) {

            int formKey = 0;
            try {
                formKey = Integer.valueOf(formKeyString);
            } catch (Exception e) {
                log.warn("Can't parse key to Integer: {}", formKey);
                continue;
            }

            int pageIndex = 0;
            int pageSize = countPerBatch;

            boolean isFirst = false;

            String lastSyncTime = reportAdjusting1stDepartmentDao.getLastSyncTime();
            log.info("last sync time: {}", lastSyncTime);

            boolean shouldContinue = false;
            do {
                shouldContinue = false;

                if (lastSyncTime == null) {
                    isFirst = true;
                }

                boolean success = true;
                do {
                    success = true;
                    try {
                        List<ReportAdjusting1stDepartmentDto> records = verintEvalDataDao.getReportAdjustingFor1stDepartmentPaged(formKey, isFirst ? null : startTimeStr, endTimeStr, pageIndex, pageSize);
                        log.info("got {} records for ReportAdjusting1stDepartment", records.size());
                        if (records.size() == countPerBatch) {
                            shouldContinue = true;
                        }

                        for (ReportAdjusting1stDepartmentDto record : records) {
                            try {
                                reportAdjusting1stDepartmentDao.insert(record);
                            } catch (Exception ex) {
                                log.error("Add report detail for ReportAdjusting1stDepartment to db exception.", ex);
                            }
                        }

                        pageIndex += pageSize;
                    } catch (Exception ex) {
                        success = false;
                    }
                } while (!success);
            }
            while (shouldContinue);
        }
    }
}
